/*
1.创建两个结构体分别为window和user，和三个变量分别为totalTime，averageTime，lastFinshTime
        （结构体的元素应该有：等待时长（程序开始后不变，越大的在前面），
        办理的时长，是否为vip（1是vip，0表示为普通用户），等待队伍时长（程序开始后开始计时））
2.创建两个队列分别为nomalQ，vipQ
3.遍历两个队列：
    A.判断是否有窗口空闲（在刚好有人办理完后，把他的办理时长加到在他之后的user表中的等待队伍时长上）
    B.如果有空闲则安排user办理业务
        （1）.先判断vip窗口是否空闲，如果空闲则安排vip用户办理（在有vip用户的情况下，没有vip用户按普通窗口处理）
        （2）.若vip窗口不空闲，则先比较vipQ的第一位和nomalQ的第一位，时间长的先办理
4.统计窗口服务数量
5.计算平均等待时间、最长等待时间和最后完成时间
6.输出结果：
    A.在一行中输出平均等待时间、最长等待时间和最后完成时间。
    B.在下一行中按照窗口编号递增的顺序输出每个窗口服务的顾客数量。
*/
#include "..\headers\ListOf.h"

#define MAX 1010

typedef struct {
  int arrivalTime;
  int processingTime;
  int isVIP;  // 1表示是vip 0表示不是vip
  int waitTime;
} Customer;

typedef struct {
  int servedCount;
  int lastServiceEndTime;
  int isVip;  // 1表示是vip窗口 0表示不是vip窗口
} Window;

// vip检查和插队
void VIPcheck(Customer C[], Window W, int &topC, int end) {
  int i, pos;
  for (i = topC; i < end; i++) {
    if (C[i].isVIP == 1 && C[i].arrivalTime < W.lastServiceEndTime) {
      pos = i;
      break;
    }
  }
  if (i < end) {  // 插队
    Customer temp = C[pos];
    for (i = pos - 1; i >= topC; i--) {
      C[i + 1] = C[i];
    }
    C[topC] = temp;
  }
}

// 顾客排队办理
int HandleCustomer(Customer C[], Window W[], int tail, int windosNumber,
                   int VIPW) {
  int top = 0;
  int i = 0, min = 0;
  while (top < tail) {  // 判断C队列是否为空

    if (C[top].isVIP == 0) {  // 为普通客户
      min = 0;
      for (i = 0; i < windosNumber; i++) {                    // 无需等待
        if (C[top].arrivalTime >= W[i].lastServiceEndTime) {  // 不需要排队
          if (W[i].isVip == 1) VIPcheck(C, W[i], top, tail);
          W[i].lastServiceEndTime = C[top].arrivalTime + C[top].processingTime;
          top++;
          W[i].servedCount++;
          break;
        }
        if (W[i].lastServiceEndTime < W[min].lastServiceEndTime) min = i;
      }
      if (i == windosNumber) {  // 来到需要等待
        if (min == VIPW) VIPcheck(C, W[min], top, tail);
        C[top].waitTime = W[min].lastServiceEndTime - C[top].arrivalTime;
        W[min].lastServiceEndTime += C[top].processingTime;
        top++;
        W[min].servedCount++;
      }
    } else {  // 为VIP用户
      if (C[top].arrivalTime >=
          W[VIPW].lastServiceEndTime) {  // 查找此时vip窗口是否空闲
        W[VIPW].lastServiceEndTime = C[top].processingTime + C[top].arrivalTime;
        W[VIPW].servedCount++;
        top++;
      } else {
        min = VIPW;
        for (i = 0; i < windosNumber; i++) {
          if (W[i].lastServiceEndTime < W[min].lastServiceEndTime) min = i;
        }
        if (C[top].arrivalTime >= W[min].lastServiceEndTime) {  // 无需等待
          W[min].lastServiceEndTime =
              C[top].arrivalTime + C[top].processingTime;
        } else {  // 需要等待
          C[top].waitTime = W[min].lastServiceEndTime - C[top].arrivalTime;
          W[min].lastServiceEndTime += C[top].processingTime;
        }
        top++;
        W[min].servedCount++;
      }
    }
  }  // end while
  return OK;
}

int main() {
  int CustomerNumber;
  int top = 0, tail = 0;
  scanf("%d", &CustomerNumber);
  // 创建两个队列分别为nomalQ，vipQ
  Customer Customers[MAX], temp;
  for (tail = 0; tail < CustomerNumber;) {
    scanf("%d %d %d", &temp.arrivalTime, &temp.processingTime, &temp.isVIP);
    if (temp.processingTime > 60) temp.processingTime = 60;
    Customers[tail++] = temp;
  }
  // 创建窗口
  int windowsNumber = 0, VIPwindow;
  scanf("%d %d", &windowsNumber, &VIPwindow);
  Window Win[windowsNumber];
  for (int i = 0; i < windowsNumber; i++) {  // 初始化
    Win[i].lastServiceEndTime = 0;
    Win[i].servedCount = 0;
    Win[i].isVip = 0;
  }
  if (VIPwindow > 0) Win[VIPwindow].isVip = 1;

  int MaxWaitTime = 0, lastFinshTime = 0;
  float averageTime = 0;
  if (top == tail) {  // 判断队列是否为空
    printf("%.1f %d %d\n", averageTime, MaxWaitTime, lastFinshTime);
    for (int i = 0; i < windowsNumber; i++) {
      printf("%d ", Win[i].servedCount);
    }
    return 0;
  }

  int State = HandleCustomer(Customers, Win, tail, windowsNumber, VIPwindow);

  if (State == OK) {  // 输出
    int sum = 0, MaxWaitTimeax = 0;
    for (int i = 0; i < CustomerNumber; i++) {
      sum += Customers[i].waitTime;
      if (Customers[i].waitTime > MaxWaitTime)
        MaxWaitTime = Customers[i].waitTime;
    }
    for (int i = 0; i < windowsNumber; i++) {
      if (Win[i].lastServiceEndTime > Win[lastFinshTime].lastServiceEndTime)
        lastFinshTime = i;
    }
    averageTime = (float)sum / CustomerNumber;
    printf("%.1f %d %d\n", averageTime, MaxWaitTime,
           Win[lastFinshTime].lastServiceEndTime);
    for (int i = 0; i < windowsNumber; i++) {
      printf("%d", Win[i].servedCount);
      if (i != windowsNumber - 1) printf(" ");
    }
    return 0;
  }
  return 0;
}
